// 仅运行于浏览器
import Vue from 'vue';
import { createApp } from './app';

const { app, router, store } = createApp();
//  数据预期，我们刚才讲到的只是服务端预取，其实还有客户端预取。什么是客户端预取呢，简单的理解就是，我们可以在路由钩子里面，找有当前路由组件没有asyncData，有的话，就去请求，获取到数据后,填充完之后，再渲染页面。
// 在客户端，在挂载到应用程序之前，store 就应该获取到状态：
Vue.mixin({
  data() {
    return {
      loading: false
    }
  },

  beforeMount() {
    const { asyncData } = this.$option;
    let data = null; // 把数据在 computed 的名称固定为 data,防止重复渲染
    try {
      data = this.data;
    } catch (e) { }

    if (asyncData && !data) { // 如果拥有 asyncData 和 data 为空的时候,进行数据加载
      this.loading = true;

      // 为当前组件的 dataPromise 赋值为这个返回的 promise，通过判断这个的运行情况来改变loading状态或者进行数据的处理 (在组件内通过this.dataPromise.then保证数据存在)
      this.dataPromise = asyncData({
        store,
        route: router.currentRoute
      });
      this.dataPromise.then(() => {
        this.loading = false;
      }).catch(e => {
        this.loading = false;
      })
    } else if (asyncData) {
      //如果存在asyncData但是已经有数据了,也就是首屏情况的话返回一个成功函数,防止组件内因为判断then来做的操作因为没有promise报错
      this.dataPromise = Promise.resolve();
    }
  }
})

if (window.__INITIAL_STATE__) {
  store.replaceState(window.__INITIAL_STATE__)
}

// service worker
function isLocalhost() {
  return /^http(s)?:\/\/localhost/.test(location.href);
}

if (('https:' === location.protocol || isLocalhost()) && navigator.serviceWorker) {
  navigator.serviceWorker.register('/service-worker.js')
}

// 由于使用的路由懒加载，所以必须要等路由提前解析完异步组件，才能正确地调用组件中可能存在的路由钩子。
router.onReady(() => {
  app.$mount('#app');
});